package com.crazymakercircle.mutithread.basic.use;

import com.crazymakercircle.util.Print;
import org.junit.Test;

import static com.crazymakercircle.util.ThreadUtil.sleepMilliSeconds;
import static com.crazymakercircle.util.ThreadUtil.sleepSeconds;

/**
 * Created by 尼恩@疯狂创客圈.
 */

/**
 * 当我们调用线程的interrupt()方法时，它有两个作用：
 * （1）如果此线程处于阻塞状态（如调用了Object.wait()方法），就会立马退出阻塞，并抛出InterruptedException异常，
 * 线程就可以通过捕获InterruptedException来做一定的处理，然后让线程退出。
 * 更确切地说，如果线程被Object.wait()、Thread.join()和Thread.sleep()三种方法之一阻塞，
 * 此时调用该线程的interrupt()方法，该线程将抛出一个InterruptedException中断异常（该线程必须事先预备好处理此异常），从而提早终结被阻塞状态。
 * （2）如果此线程正处于运行之中，线程就不受任何影响，继续运行，
 * 仅仅是线程的中断标记被设置为true。所以，程序可以在适当的位置通过调用isInterrupted()方法来查看自己是否被中断，并执行退出操作。
 *
 * @author Marion
 * @date 2021/6/11 18:55
 */
public class InterruptDemo
{

    public static final int SLEEP_GAP = 5000;//睡眠时长
    public static final int MAX_TURN = 50;//睡眠次数

    static class SleepThread extends Thread
    {
        static int threadSeqNumber = 1;

        public SleepThread()
        {
            super("sleepThread-" + threadSeqNumber);
            threadSeqNumber++;
        }

        @Override
        public void run()
        {
            try
            {
                Print.tco(getName() + " 进入睡眠.");
                // 线程睡眠一会
                Thread.sleep(SLEEP_GAP);
            } catch (InterruptedException e)
            {
                e.printStackTrace();
                Print.tco(getName() + " 发生被异常打断.");
                return;
            }
            Print.tco(getName() + " 运行结束.");
        }

    }

    public static void main(String args[]) throws InterruptedException
    {
        /**
         * 如果线程的interrupt()方法先被调用，然后线程开始调用阻塞方法进入阻塞状态，InterruptedException异常依旧会抛出。
         * 如果线程捕获InterruptedException异常后，继续调用阻塞方法，将不再触发InterruptedException异常。
         */

        Thread thread1 = new SleepThread();
        thread1.start();
        Thread thread2 = new SleepThread();
        thread2.start();
        sleepSeconds(2);//等待2秒
        thread1.interrupt(); //打断线程1
        sleepSeconds(5);//等待5秒
        thread2.interrupt();  //打断线程2，此时线程2已经终止
        sleepSeconds(1);//等待1秒
        Print.tco("程序运行结束.");
    }

    //测试用例：获取异步调用的结果
    @Test
    public void testInterrupted2()
    {
        Thread thread = new Thread()
        {
            public void run()
            {
                Print.tco("线程启动了");
                //一直循环
                while (true)
                {
                    Print.tco(isInterrupted());
                    sleepMilliSeconds(SLEEP_GAP);

                    //如果调用 interrupt 为true，退出死循环
                    if (isInterrupted())
                    {
                        Print.tco("线程结束了");
                        return;
                    }
                }
            }
        };
        thread.start();
        sleepSeconds(2);//等待2秒
        thread.interrupt(); //打断线程1
        sleepSeconds(2);//等待2秒
        thread.interrupt();
    }
}